﻿using System;
using System.Collections.Generic;
using System.Text;
using MigratorCore.Actions;
using MigratorCore.Status;
using MigratorCore.Bases;
using MigratorCore.Objects;
using System.Data.SqlClient;
using System.Data;
using System.Data.SqlTypes;

namespace Migrator.CommunityServer.version2007_1
{
    public class ForumsSource : ISourceAction
    {
        #region ISourceAction Members

        public void Get()
        {
            objects = new ObjectSet();
            status.AddEvent(new Event(EventType.Information, "Initializing", "Initializing Action", DateTime.Now));
            SqlConnection con = new SqlConnection(settings["ConnectionString"].ToString());
            SqlDataReader read;
            #region Get Structure and test data connection
            SqlCommand sc = new SqlCommand("SELECT cs_Groups.[Name] AS GroupName, cs_Sections.SectionID, cs_Sections.[Name], cs_Sections.Description FROM cs_SiteSettings INNER JOIN cs_Sections ON cs_SiteSettings.SettingsID = cs_Sections.SettingsID LEFT OUTER JOIN cs_Groups ON cs_Sections.GroupID = cs_Groups.GroupID WHERE cs_SiteSettings.ApplicationName = '" + settings["Application Name"].ToString() + "' AND cs_Sections.ApplicationType = 0", con);
            try
            {
                con.Open();
                read = sc.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
            }
            catch (Exception e)
            {
                status.Completed = 100;
                status.AddEvent(new Event(EventType.CriticalError, "Data Connection Failed!", e.Message, e, DateTime.Now));
                return;
            }
            int x = 0;
            status.AddEvent(new Event(EventType.Information, "Loading Forum Structre", "Loaded Forum Structre from Source", DateTime.Now));
            while (read.Read())
            {
                x++;
                bool added = false;
                foreach (Forum forum in this.Objects)
                    if (forum.Name.Equals(read.GetString(0)))
                    {
                        Forum f = new Forum(read.GetString(2), read.GetString(3));
                        parseForums(f, read.GetInt32(1));
                        forum.Forums.Add(f);
                        added = true;
                    }
                if (!added)
                {
                    Forum f = new Forum(read.GetString(0), "");
                    Forum f2 = new Forum(read.GetString(2), read.GetString(3));
                    parseForums(f2, read.GetInt32(1));
                    f.Forums.Add(f2);
                    this.Objects.Add(f);
                }

            }
            sc.Dispose();
            status.AddEvent(new Event(EventType.Information, "Loaded " + x.ToString() + " Forums and Groups", "Loaded " + x.ToString() + " Forums, Sub Forums and Groups from Source", DateTime.Now));
            #endregion
        }

        #endregion

        private void parseForums(Forum forum, int sectionid)
        {
            #region Get Forum Posts
            int x = 0;
            SqlDataAdapter apt = new SqlDataAdapter("SELECT cs_Posts.ParentID, cs_Posts.PostID, cs_Users.UserName, cs_Users.Email, cs_Posts.Subject, cs_Posts.PostDate, cs_Posts.Body FROM cs_Posts INNER JOIN cs_Users ON cs_Posts.UserID = cs_Users.UserID WHERE cs_Posts.SectionID = " + sectionid.ToString() + " ORDER BY PostID", settings["ConnectionString"].ToString());
            DataSet ds = new DataSet();
            apt.Fill(ds);
            foreach (DataRow row in ds.Tables[0].Rows)
            {
                if (int.Parse(row["PostID"].ToString()) == int.Parse(row["ParentID"].ToString()))
                {
                    status.AddEvent(new Event(EventType.Information, "Processing Thread " + row["PostID"].ToString(), "Processing Thread " + row["Subject"].ToString() + " (" + row["PostID"].ToString() + ")", DateTime.Now));
                    Post p = new Post();
                    p.Body = row["Body"].ToString();
                    p.Name = row["PostID"].ToString();
                    p.Subject = row["Subject"].ToString();
                    p.User = new User(row["UserName"].ToString(), row["Email"].ToString());
                    p.Posted = SqlDateTime.Parse(row["PostDate"].ToString()).Value;
                    ParseThread(p, ds, ref x);
                    x++;
                    double aa = 0.00 + ds.Tables[0].Rows.Count;
                    status.Completed = Convert.ToInt32(Math.Round(Convert.ToDecimal(((x + 1) / aa) * 100), 0));
                    status.AddEvent(new Event(EventType.Information, "Processed Thread " + row["PostID"].ToString(), "Processed Thread " + row["Subject"].ToString() + " (" + row["PostID"].ToString() + ")", DateTime.Now));
                }
            }
            #endregion
        }

        private void ParseThread(Post post, DataSet ds, ref int x)
        {
            foreach (DataRow row in ds.Tables[0].Rows)
            {
                if (int.Parse(row["ParentID"].ToString()) == int.Parse(post.Name))
                {
                    x++;
                    Post p = new Post();
                    p.Body = row["Body"].ToString();
                    p.Name = row["PostID"].ToString();
                    p.Subject = row["Subject"].ToString();
                    p.User = new User(row["UserName"].ToString(), row["Email"].ToString());
                    p.Posted = SqlDateTime.Parse(row["PostDate"].ToString()).Value;
                    double aa = 0.00 + ds.Tables[0].Rows.Count;
                    status.Completed = Convert.ToInt32(Math.Round(Convert.ToDecimal(((x + 1) / aa) * 100), 0));
                    status.AddEvent(new Event(EventType.Information, "Processed Post " + row["PostID"].ToString(), "Processed Post " + row["Subject"].ToString() + " (" + row["PostID"].ToString() + ")", DateTime.Now));
                    ParseThread(p, ds, ref x);
                    post.Posts.Add(p);
                }
            }
        }

        #region IAction Members

        public string Name
        {
            get { return "Forums Source"; }
        }

        private Status status;
        public MigratorCore.Status.Status Status
        {
            get
            {
                if (status == null)
                    status = new Status();
                return status;
            }
        }

        private ObjectSet objects;
        public MigratorCore.Objects.ObjectSet Objects
        {
            get
            {
                if (this.objects == null) this.objects = new ObjectSet();
                return this.objects;
            }
            set
            {
                this.objects = value;
            }
        }

        public MigratorCore.ActionType ActionType
        {
            get { return MigratorCore.ActionType.Forums; }
        }

        private Settings settings;
        public Settings Settings
        {
            get
            {
                if (settings == null)
                {
                    settings = new Settings();
                    settings.Add("ConnectionString", "server=(localhost);uid=;pwd=;Trusted_Connection=yes;database=CommunityServer");
                    settings.Add("Application Name", "dev");
                }
                return settings;
            }
        }

        #endregion
    }
}
